"""
1289. 下降路径最小和 II
困难
相关标签
相关企业
提示
给你一个 n x n 整数矩阵 grid ，请你返回 非零偏移下降路径 数字和的最小值。

非零偏移下降路径 定义为：从 grid 数组中的每一行选择一个数字，且按顺序选出来的数字中，相邻数字不在原数组的同一列。



示例 1：



输入：grid = [[1,2,3],[4,5,6],[7,8,9]]
输出：13
解释：
所有非零偏移下降路径包括：
[1,5,9], [1,5,7], [1,6,7], [1,6,8],
[2,4,8], [2,4,9], [2,6,7], [2,6,8],
[3,4,8], [3,4,9], [3,5,7], [3,5,9]
下降路径中数字和最小的是 [1,5,7] ，所以答案是 13 。
示例 2：

输入：grid = [[7]]
输出：7


提示：

n == grid.length == grid[i].length
1 <= n <= 200
-99 <= grid[i][j] <= 99
"""
import math


class Solution(object):
    def minFallingPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        m = len(grid)
        n = len(grid[0])
        dp = [[0] * n for _ in range(m)]
        # m = 0
        for i in range(m):
            for j in range(n):
                dp[i][j] = grid[i][j]
        #
        for i in range(1, m):
            before = dp[i - 1]
            #创建索引
            iList = list(range(0,n))
            #iList索引根据before的值排序
            iList.sort(key=lambda x: before[x])

            for j in range(n):
            #获取dp[i-1]最小值，下一层都是通过最小值到达，如果在同一列则从第二小
                if j == iList[0]:
                    #在同一列则从第二小
                    dp[i][j] += before[iList[1]]
                else:
                    #不在同一列则从最小值
                    dp[i][j] += before[iList[0]]
        return min(dp[-1])
    def minFallingPathSum_my1(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        m = len(grid)
        n = len(grid[0])
        dp = [[0] * n for _ in range(m)]
        # m = 0
        for i in range(n):
            dp[0][i] = grid[0][i]
        #
        for i in range(1, m):
            for j in range(n):
                dp[i][j] = float('inf')
                for k in range(n):
                    if j == k:
                        continue
                    dp[i][j] = min(dp[i][j], dp[i - 1][k] + grid[i][j])
        return min(dp[-1])
    def minFallingPathSum_Res1(self, grid):
        m,n = len(grid),len(grid[0])
        dp = grid[0]
        for i in range(1,m):
            mindp = min(dp)
            mindp_id = dp.index(mindp)
            dp[mindp_id] = float("inf")
            mindp2 = min(dp)
            for j in range(n):
                if j == mindp_id:
                    dp[j] = mindp2+grid[i][j]
                else:
                    dp[j] = mindp+grid[i][j]
        return min(dp)

if __name__ == '__main__':
    #测试
    print(Solution().minFallingPathSum([[1,2,3],[4,5,6],[7,8,9]]))
